﻿using PatientManagement.Common.ObjectModels;
using PatientManagement.Managers;
using PatientManagement.Common.Utils;

using System;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using DBObject = PatientManagement.Database;
using System.Drawing;

namespace PatientManagement
{
    public partial class FormMain : Form
    {
        #region Printing Variables

        StringFormat strFormat; //Used to format the grid rows.
        ArrayList arrColumnLefts = new ArrayList();//Used to save left coordinates of columns
        ArrayList arrColumnWidths = new ArrayList();//Used to save column widths
        int iCellHeight = 0; //Used to get/set the datagridview cell height
        int iTotalWidth = 0; //
        int iRow = 0;//Used as counter
        bool bFirstPage = false; //Used to check whether we are printing first page
        bool bNewPage = false;// Used to check whether we are printing a new page
        int iHeaderHeight = 0; //Used for the header height

        #endregion

        private static List<Drug> m_Drugs;
        private int m_ParentId;

        public FormMain()
        {
            InitializeComponent();
            InitData();
        }

        #region Events

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (HasErrorText() && gvPrescription.Rows.Count < 2)
            {
                MessageBox.Show("Bạn cần nhập chính xác các thông tin trước khi lưu!", "Thông báo", MessageBoxButtons.OK);
                return;
            }

            if (string.IsNullOrEmpty(tbPatientName.Text.Trim()))
            {
                MessageBox.Show("Bạn phải nhập tên bệnh nhân!", "Thông báo", MessageBoxButtons.OK);
            }
            else
            {
                if (m_ParentId != -1)
                {
                    var prescription = new DBObject.Prescription()
                    {
                        Created = DateTime.Now,
                        Description = string.Empty,
                        Diagnostic = tbDiagnostic.Text.Trim(),
                        PatientId = m_ParentId,
                        Prognostic = tbPrognostic.Text.Trim()
                    };

                    var prescriptionId = ServiceManager.Instance.AddPrescription(prescription);

                    if (prescriptionId != -1)
                    {
                        for (int i = 0; i < gvPrescription.Rows.Count - 1; i++)
                        {
                            var prescriptionDetail = new DBObject.PrescriptionDetail()
                            {
                                PrescriptionId = prescriptionId,
                                DrugId = Convert.ToInt32(gvPrescription["colDrugName", i].Value),
                                Price = Convert.ToInt64(gvPrescription["colPrice", i].Value),
                                Amount = Convert.ToDecimal(gvPrescription["colVolume", i].Value),
                                Usage = gvPrescription["colUsage", i].Value == null ? string.Empty : gvPrescription["colUsage", i].Value.ToString()
                            };

                            ServiceManager.Instance.AddPrescriptionDetail(prescriptionDetail);

                            //Update volume of drug in database
                            var oldDrug = m_Drugs.Find(item => item.Id == Convert.ToInt32(gvPrescription["colDrugName", i].Value));
                            if (oldDrug != null)
                            {
                                oldDrug.Amount = oldDrug.Amount - Convert.ToDecimal(gvPrescription["colVolume", i].Value);
                                if (oldDrug.Amount <= 0)
                                {
                                    oldDrug.Amount = 0;
                                    MessageBox.Show(string.Format("Đã hết thuốc {0} trong kho", oldDrug.Name));
                                }
                                ServiceManager.Instance.UpdateDrug(oldDrug);
                            }
                        }
                        gvPrescription.Enabled = false;
                        MessageBox.Show("Thêm thành công!", "Thông báo", MessageBoxButtons.OK);
                    }
                }
                else
                {
                    MessageBox.Show("Thêm không thành công!", "Thông báo", MessageBoxButtons.OK);
                }
            }
        }

        private void manageDrugtt_Click(object sender, EventArgs e)
        {
            FormDrugManagement from = new FormDrugManagement();
            from.ShowDialog();
        }

        private void ManagePatient_Click(object sender, EventArgs e)
        {
            FormPatientManagement form = new FormPatientManagement();
            form.ShowDialog();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            FormAddPatient form = new FormAddPatient();
            form.ShowDialog();
            if (form.PatientId != -1)
            {
                m_ParentId = form.PatientId;
                GetPatientById(form.PatientId);
            }
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            FormSearchPatient form = new FormSearchPatient();
            form.ShowDialog();
            if (form.PatientId != -1)
            {
                m_ParentId = form.PatientId;
                GetPatientById(form.PatientId);
            }
        }
                                                         
        private void gvPrescription_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            if (e.Control is ComboBox)
            {
                var cbo = e.Control as ComboBox;

                cbo.DropDownStyle = ComboBoxStyle.DropDown;
                cbo.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                cbo.AutoCompleteSource = AutoCompleteSource.ListItems;
            }

            if (gvPrescription.CurrentCell.ColumnIndex == gvPrescription.Columns["colVolume"].Index ||
                gvPrescription.CurrentCell.ColumnIndex == gvPrescription.Columns["colPrice"].Index
                )
            {
                TextBox item = e.Control as TextBox;
                if (item != null)
                {
                    item.KeyPress += new KeyPressEventHandler(item_KeyPress);
                }
            }
            else
            {
                TextBox allowText = e.Control as TextBox;
                if (allowText != null)
                {
                    allowText.KeyPress += new KeyPressEventHandler(allowText_KeyPress);
                }
            }
        }

        private void allowText_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = false;
        }

        private void item_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsControl(e.KeyChar)
                && !char.IsDigit(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        private void gvPrescription_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            Drug drug = null;
            if (e.RowIndex != -1 && e.ColumnIndex == gvPrescription.Columns["colVolume"].Index)
            {
                if (gvPrescription["colDrugName", e.RowIndex].Value != null)
                {
                    int drugId = (int)gvPrescription["colDrugName", e.RowIndex].Value;
                    drug = m_Drugs.Find(item => item.Id == drugId);
                }
            }
            else if (e.RowIndex != -1 && e.ColumnIndex == gvPrescription.Columns["colDrugName"].Index)
            {
                if (gvPrescription["colVolume", e.RowIndex].Value != null)
                {
                    int drugId = (int)gvPrescription["colDrugName", e.RowIndex].Value;
                    drug = m_Drugs.Find(item => item.Id == drugId);
                }
            }

            if (drug != null)
            {
                gvPrescription["colPrice", e.RowIndex].Value = Convert.ToInt64(drug.Price);
                gvPrescription["colTotalPrice", e.RowIndex].Value =
                    (Convert.ToInt64(gvPrescription["colVolume", e.RowIndex].Value) * Convert.ToInt64(drug.Price));

                CalcTotalOfMoney();
            }
        }

        private void gvPrescription_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == gvPrescription.Columns["colDelete"].Index &&
                ((gvPrescription.Rows.Count - 1) != e.RowIndex))
            {
                gvPrescription.Rows.RemoveAt(e.RowIndex);
            }
        }

        private void templateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormTemplateManagement form = new FormTemplateManagement();
            form.ShowDialog();
        }

        private void addDrugToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormAddDrug form = new FormAddDrug();
            form.ShowDialog();
        }

        private void addTemplateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormAddTemplate form = new FormAddTemplate();
            form.ShowDialog();
        }

        private void cboTempPrescription_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cboTempPrescription.SelectedIndex != 0)
            {
                gvPrescription.Rows.Clear();
                var item = cboTempPrescription.SelectedItem as DBObject.PrescriptionTemplate;
                List<DBObject.PrescriptionTempDetail> prescriptionTempDetail = ServiceManager.Instance.GetPrescriptionTempDetail(item.Id);
                if (prescriptionTempDetail.Count != 0)
                {
                    var drugs = new List<Drug>();
                    prescriptionTempDetail.ForEach(prescription =>
                    {
                        var drug = m_Drugs.Find(d => d.Id == prescription.DrugId);
                        if (drug != null)
                        {
                            drug.Map(i => gvPrescription.Rows.Add(i.Id, Convert.ToInt64(prescription.Amount), prescription.Usage,
                                Convert.ToInt64(i.Price), Convert.ToInt64(prescription.Amount * i.Price)));
                        }
                    });

                    CalcTotalOfMoney();
                }
            }
        }

        private void gvPrescription_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            if (gvPrescription["colDrugName", e.RowIndex].Value == null ||
                gvPrescription["colVolume", e.RowIndex].Value == null ||
                gvPrescription["colPrice", e.RowIndex].Value == null)
            {
                gvPrescription.Rows[e.RowIndex].ErrorText = "Bạn phải nhập đầy đủ các thông tin về thuốc. Cách dùng có thể bỏ qua!";
            }
        }

        private void gvPrescription_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            gvPrescription.Rows[e.RowIndex].ErrorText = string.Empty;
        }

        private void menuToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void infoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new FormAbout().Show();
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
        }

        #endregion

        #region Private methods

        private void GetPatientById(int id)
        {
            var patient = ServiceManager.Instance.GetPatientById(id);
            if (patient != null)
            {
                tbPatientName.Text = patient.Name;
                tbAddress.Text = patient.Address;
                dtpBirthday.Value = patient.Birthday;
                tbPhoneNumber.Text = patient.PhoneNumber;
                lbPatientId.Text = patient.PatientId;

                HandleControls();
            }
        }

        public void HandleControls()
        {
            gvPrescription.Rows.Clear();
            gvPrescription.Enabled = true;
            cboTempPrescription.Enabled = true;
            btnSave.Enabled = true;
            cboTempPrescription.SelectedIndex = 0;
            lbTotal.Text = string.Empty;
        }

        private void InitData()
        {
            m_Drugs = new List<Drug>();
            m_Drugs = ServiceManager.Instance.GetAllGrugs();
            colDrugName.DataSource = m_Drugs;
            colDrugName.ValueMember = "Id";
            colDrugName.DisplayMember = "Name";

            List<DBObject.PrescriptionTemplate> tempPrescriptions = ServiceManager.Instance.GetPrescriptionTemplates();
            tempPrescriptions.Insert(0, new DBObject.PrescriptionTemplate() { Id = 0, Name = "" });
            cboTempPrescription.DataSource = tempPrescriptions;
            cboTempPrescription.ValueMember = "Id";
            cboTempPrescription.DisplayMember = "Name";
            cboTempPrescription.DropDownStyle = ComboBoxStyle.DropDown;
            cboTempPrescription.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            cboTempPrescription.AutoCompleteSource = AutoCompleteSource.ListItems;
        }

        private void CalcTotalOfMoney()
        {
            long total = 0;
            for (int i = 0; i < gvPrescription.Rows.Count - 1; i++)
            {
                total += Convert.ToInt64(gvPrescription["colTotalPrice", i].Value);
            }
            lbTotal.Text = total != 0 ? total.ToString("0,00.## đ") : string.Empty;
        }

        private bool HasErrorText()
        {
            bool hasErrorText = false;
            foreach (DataGridViewRow row in gvPrescription.Rows)
            {
                if (!string.IsNullOrEmpty(row.ErrorText))
                {
                    hasErrorText = true;
                }
                if (hasErrorText)
                    break;
            }

            return hasErrorText;
        }

        #endregion

        #region Printing

        private void btnPrint_Click(object sender, EventArgs e)
        {
            PrintDialog printDialog = new PrintDialog();
            printDialog.Document = printDocument;
            printDialog.UseEXDialog = true;

            //PrintPreviewDialog objPPdialog = new PrintPreviewDialog();
            //objPPdialog.Document = printDocument;
            //objPPdialog.ShowDialog();

            if (DialogResult.OK == printDialog.ShowDialog())
            {
                printDocument.DocumentName = "Đơn thuốc";
                printDocument.Print();
            }
        }





        private void printDocument_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
        {
            try
            {
                strFormat = new StringFormat();
                strFormat.Alignment = StringAlignment.Near;
                strFormat.LineAlignment = StringAlignment.Center;
                strFormat.Trimming = StringTrimming.EllipsisCharacter;

                arrColumnLefts.Clear();
                arrColumnWidths.Clear();
                iCellHeight = 0;
                iRow = 0;
                bFirstPage = true;
                bNewPage = true;

                // Calculating Total Widths
                iTotalWidth = 0;
                foreach (DataGridViewColumn dgvGridCol in gvPrescription.Columns)
                {
                    iTotalWidth += dgvGridCol.Width;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Lỗi trong khi bắt đầu in. Xin thử lại!", "Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            try
            {
                //Set the left margin
                int iLeftMargin = e.MarginBounds.Left;
                //Set the top margin
                int iTopMargin = e.MarginBounds.Top;
                //Whether more pages have to print or not
                bool bMorePagesToPrint = false;
                int iTmpWidth = 0;

                //For the first page to print set the cell width and header height
                if (bFirstPage)
                {
                    foreach (DataGridViewColumn GridCol in gvPrescription.Columns)
                    {
                        if (GridCol.Index == gvPrescription.Columns["colDrugName"].Index ||
                            GridCol.Index == gvPrescription.Columns["colVolume"].Index ||
                            GridCol.Index == gvPrescription.Columns["colUsage"].Index)
                        {
                            iTmpWidth = (int)(Math.Floor((double)((double)GridCol.Width /
                                           (double)iTotalWidth * (double)iTotalWidth *
                                           ((double)e.MarginBounds.Width / (double)iTotalWidth))));

                            iHeaderHeight = (int)(e.Graphics.MeasureString(GridCol.HeaderText,
                                        GridCol.InheritedStyle.Font, iTmpWidth).Height) + 11;

                            // Save width and height of headres
                            if (GridCol.Index == gvPrescription.Columns["colUsage"].Index)
                            {
                                iTmpWidth = iTmpWidth + e.MarginBounds.Left + 20;
                            }
                            arrColumnLefts.Add(iLeftMargin);
                            arrColumnWidths.Add(iTmpWidth);
                            iLeftMargin += iTmpWidth;
                        }
                    }
                }
                //Loop till all the grid rows not get printed
                while (iRow <= gvPrescription.Rows.Count - 1)
                {
                    DataGridViewRow GridRow = gvPrescription.Rows[iRow];
                    //Set the cell height
                    iCellHeight = GridRow.Height + 5;
                    int iCount = 0;
                    //Check whether the current page settings allo more rows to print
                    if (iTopMargin + iCellHeight >= e.MarginBounds.Height + e.MarginBounds.Top)
                    {
                        bNewPage = true;
                        bFirstPage = false;
                        bMorePagesToPrint = true;
                        break;
                    }
                    else
                    {
                        if (bNewPage)
                        {
                            //Draw Header
                            e.Graphics.DrawString("Đơn thuốc", new Font("Times New Roman", 30, FontStyle.Bold),
                                    Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top -
                                    e.Graphics.MeasureString("Đơn thuốc", new Font("Times New Roman", 30, FontStyle.Bold), e.MarginBounds.Width).Height);

                            String strDate = DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToShortTimeString();

                            //Draw Date
                            e.Graphics.DrawString(strDate, new Font(gvPrescription.Font, FontStyle.Italic),
                                    Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width -
                                    e.Graphics.MeasureString(strDate, new Font(gvPrescription.Font,
                                    FontStyle.Bold), e.MarginBounds.Width).Width), e.MarginBounds.Top -
                                    e.Graphics.MeasureString("Đơn thuốc", new Font(new Font(gvPrescription.Font,
                                    FontStyle.Bold), FontStyle.Bold), e.MarginBounds.Width).Height - 13);

                            //Info
                            e.Graphics.DrawString(string.Format("ID: {0}", lbPatientId.Text), new Font("Times New Roman", 13, FontStyle.Bold),
                                   Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + 30);

                            e.Graphics.DrawString(string.Format("Tên bệnh nhân: {0}", tbPatientName.Text), new Font("Times New Roman", 13, FontStyle.Bold),
                                   Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + 60);

                            e.Graphics.DrawString(string.Format("Năm sinh: {0}", dtpBirthday.Value.ToShortDateString()), new Font("Times New Roman", 13, FontStyle.Bold),
                                   Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + 90);

                            e.Graphics.DrawString(string.Format("Địa chỉ: {0}", tbAddress.Text), new Font("Times New Roman", 13, FontStyle.Bold),
                                   Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + 120);

                            e.Graphics.DrawString(string.Format("Số điện thoại: {0}", tbPhoneNumber.Text), new Font("Times New Roman", 13, FontStyle.Bold),
                                   Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + 150);

                            e.Graphics.DrawString(string.Format("Triệu chứng: {0}", tbPrognostic.Text), new Font("Times New Roman", 13, FontStyle.Bold),
                                   Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + 180);

                            e.Graphics.DrawString(string.Format("Chuẩn đoán: {0}", tbDiagnostic.Text), new Font("Times New Roman", 13, FontStyle.Bold),
                                  Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top + 210);

                            //Draw Columns                 
                            iTopMargin = e.MarginBounds.Top + 300;
                            foreach (DataGridViewColumn GridCol in gvPrescription.Columns)
                            {
                                if (GridCol.Index == gvPrescription.Columns["colDrugName"].Index ||
                                    GridCol.Index == gvPrescription.Columns["colVolume"].Index ||
                                    GridCol.Index == gvPrescription.Columns["colUsage"].Index)
                                {
                                    e.Graphics.FillRectangle(new SolidBrush(Color.LightGray),
                                        new Rectangle((int)arrColumnLefts[iCount], iTopMargin,
                                        (int)arrColumnWidths[iCount], iHeaderHeight));

                                    e.Graphics.DrawRectangle(Pens.Black,
                                        new Rectangle((int)arrColumnLefts[iCount], iTopMargin,
                                        (int)arrColumnWidths[iCount], iHeaderHeight));

                                    e.Graphics.DrawString(GridCol.HeaderText, GridCol.InheritedStyle.Font,
                                        new SolidBrush(GridCol.InheritedStyle.ForeColor),
                                        new RectangleF((int)arrColumnLefts[iCount], iTopMargin,
                                        (int)arrColumnWidths[iCount], iHeaderHeight), strFormat);
                                    iCount++;
                                }
                            }
                            bNewPage = false;
                            iTopMargin += iHeaderHeight;
                        }
                        iCount = 0;
                        //Draw Columns Contents                
                        foreach (DataGridViewCell Cel in GridRow.Cells)
                        {
                            if (iCount >= 3) { break; }
                            if (Cel.Value != null)
                            {
                                e.Graphics.DrawString(Cel.FormattedValue.ToString(), Cel.InheritedStyle.Font,
                                            new SolidBrush(Cel.InheritedStyle.ForeColor),
                                            new RectangleF((int)arrColumnLefts[iCount], (float)iTopMargin,
                                            (int)arrColumnWidths[iCount], (float)iCellHeight), strFormat);
                            }
                            //Drawing Cells Borders 
                            e.Graphics.DrawRectangle(Pens.Black, new Rectangle((int)arrColumnLefts[iCount],
                                    iTopMargin, (int)arrColumnWidths[iCount], iCellHeight));

                            iCount++;
                        }
                    }
                    iRow++;
                    iTopMargin += iCellHeight;
                }

                e.Graphics.DrawString(string.Format("Chữ ký", tbDiagnostic.Text), new Font("Times New Roman", 13, FontStyle.Bold),
                                  Brushes.Black, (int)arrColumnLefts[arrColumnLefts.Count - 1] + e.MarginBounds.Left + 50, iTopMargin + 30);

                //If more lines exist, print another page.
                if (bMorePagesToPrint)
                    e.HasMorePages = true;
                else
                    e.HasMorePages = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Lỗi trong khi in. Xin thử lại!", "Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion
    }
}
